/* 
  SZARP: SCADA software 
  
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/
/*
 * draw3
 * SZARP
 
 * Michał Blajerski <nameless@praterm.com.pl>
 *
 * $Id$
 * Mini toolbar to control menubar and most used draw3 functions.
 */


#include <wx/config.h>
#include <wx/xrc/xmlres.h>

#include "ids.h"
#include "drawtb.h"
#include "vercheck.h"
#include "bitmaps/help.xpm"
#include "bitmaps/exit.xpm"
#include "bitmaps/find.xpm"
#include "bitmaps/plus.xpm"
#include "bitmaps/split.xpm"
#include "bitmaps/filter0.xpm"
#include "bitmaps/filter1.xpm"
#include "bitmaps/filter2.xpm"
#include "bitmaps/filter3.xpm"
#include "bitmaps/filter4.xpm"
#include "bitmaps/filter5.xpm"
#include "bitmaps/refresh.xpm"
#include "bitmaps/remark.xpm"
#include "bitmaps/flag_checkered.xpm"
#include "bitmaps/oldverwarn.xpm"
#include "bitmaps/draw_tree.xpm"
#include "bitmaps/florence.xpm"

#include "errfrm.h"
#include "ids.h"
#include "szframe.h"

#include <wx/checkbox.h>
#include <wx/textctrl.h>
#include <wx/config.h>
#include <wx/xrc/xmlres.h>
#include <wx/cshelp.h>

#include <algorithm>
#include <unordered_map>

#ifndef MINGW32
std::string exec_cmd (const char* cmd)
{
	char buffer[128];
	std::string result = "";
	FILE* pipe = popen(cmd, "r");

	if (!pipe)
		return "";

	while (!feof(pipe)) {
		if (NULL != fgets(buffer, 128, pipe))
			result += buffer;
	}

	pclose(pipe);
	return result;
}
#endif

namespace {
	const int DEFAULT_ICON_SIZE = 16;

	wxBitmap ResizeXPM(const char **xpm, const int multi){
		const int size = DEFAULT_ICON_SIZE * multi;
		wxBitmap bmp = wxBitmap(xpm);
		if (bmp.GetWidth() == size || bmp.GetHeight() == size)
			return bmp;
		wxImage image = bmp.ConvertToImage();
		bmp = wxBitmap(image.Scale(size, size));
		return bmp;
	}

	const std::unordered_map<int, int> xrcidToZoom = {
		{XRCID("IconsZoom1X"), 1},
		{XRCID("IconsZoom2X"), 2},
		{XRCID("IconsZoom4X"), 4},
		{XRCID("IconsZoom6X"), 6}
	};

	template<typename K, typename V>
	typename std::unordered_map<K, V>::const_iterator
	FindByValue(const std::unordered_map<K, V>& map, const V& value) {
		auto it = std::find_if(map.cbegin(), map.cend(),
			[&value](const auto& element) {
				return element.second == value;
			}
		);
		return it;
	}
}

const wxString DrawToolBar::AllowedZoomsList = "1, 2, 4, 6";

DrawToolBar::DrawToolBar(wxWindow *parent, int icons_zoom) :
	wxToolBar(parent,-1)
{
	SetHelpText(_T("draw3-toolbar-items"));
	if (!IsAllowedZoom(icons_zoom)) {
		icons_zoom = 1;
	}
	Redraw(icons_zoom);
	VersionChecker::AddToolbar(this);
}

void DrawToolBar::Redraw(const int icons_zoom) {
	ClearTools();

	AddTool(drawTB_ABOUT, _T(""), ResizeXPM(help_xpm, icons_zoom), _("About"));
	AddTool(drawTB_FIND, _T(""), ResizeXPM(find_xpm, icons_zoom), _("Find"));
	AddTool(drawTB_SUMWIN, _T(""), ResizeXPM(plus_xpm, icons_zoom), _("Summary Window"));
	AddTool(drawTB_SPLTCRS, _T(""), ResizeXPM(split_xpm, icons_zoom), _("Split cursor"), wxITEM_CHECK);
	AddTool(drawTB_FILTER, _T(""), ResizeXPM(filter0_xpm, icons_zoom), _("Filter"));
	AddTool(drawTB_REFRESH, _T(""), ResizeXPM(refresh_xpm, icons_zoom), _("Refresh"));
	AddTool(drawTB_DRAWTREE, _T(""), ResizeXPM(draw_tree_xpm, icons_zoom), _("Tree Set"));
/** disable florence keyboard in windows builds */
#ifndef MINGW32
	AddTool(drawTB_FLORENCE, _T(""), ResizeXPM(florence_xpm, icons_zoom), _("Show screen keyboard"));
#endif
	AddTool(drawTB_GOTOLATESTDATE, _T(""), ResizeXPM(flag_checkered_xpm, icons_zoom), _("Go to latest date"));
	AddTool(drawTB_REMARK, _T(""), ResizeXPM(remark_xpm, icons_zoom), _("Remarks"));
	AddTool(drawTB_EXIT, _T(""), ResizeXPM(exit_xpm, icons_zoom), _("Quit"));

	if (VersionChecker::IsNewVersion())
		NewDrawVersionAvailable();
	else
		Realize();

#ifndef MINGW32
	/* disable florence button if program is not present */
	std::string path = exec_cmd("which florence");
	path = path.substr(0, path.size()-1);

	if (access(path.c_str(), X_OK))
		EnableTool(drawTB_FLORENCE, false);
#endif
	Layout();
	Realize();
}

void DrawToolBar::DoubleCursorToolCheck() {
	ToggleTool(drawTB_SPLTCRS, true);
}

void DrawToolBar::DoubleCursorToolUncheck() {
	ToggleTool(drawTB_SPLTCRS, false);
}

void DrawToolBar::NewDrawVersionAvailable() {
	int index = GetToolPos(drawTB_EXIT);
	InsertTool(index, drawTB_NEWDRAWVERSION, wxEmptyString, old_version_warning_xpm, wxNullBitmap, wxITEM_NORMAL, _T(""), _("New version available"), NULL);
	Realize();
}

void DrawToolBar::SetFilterToolIcon(int i) {
	char const **tool_icon;

	switch (i) {
		case 0:
			tool_icon = filter0_xpm;
			break;
		case 1:
			tool_icon = filter1_xpm;
			break;
		case 2:
			tool_icon = filter2_xpm;
			break;
		case 3:
			tool_icon = filter3_xpm;
			break;
		case 4:
			tool_icon = filter4_xpm;
			break;
		case 5:
			tool_icon = filter5_xpm;
			break;
		default:
			assert(false);
	}
	int index = GetToolPos(drawTB_FILTER);
	assert(index != wxNOT_FOUND);

	DeleteTool(drawTB_FILTER);
	InsertTool(index, drawTB_FILTER, wxEmptyString, tool_icon, wxNullBitmap, wxITEM_NORMAL, _T(""), _("Filter"), NULL);
	Realize();
}

void DrawToolBar::NewVersionToolClicked(wxCommandEvent &e) {
	VersionChecker::ShowNewVersionMessage();
}

DrawToolBar::~DrawToolBar() {
	VersionChecker::RemoveToolbar(this);
}

bool DrawToolBar::IsAllowedZoom(const int icons_zoom) {
	return FindByValue(xrcidToZoom, icons_zoom) != xrcidToZoom.cend();
}

bool DrawToolBar::GetXRCIDFromZoom(const int icons_zoom, int& xrcid) {
	auto it = FindByValue(xrcidToZoom, icons_zoom);

	if (it != xrcidToZoom.end()) {
		xrcid = it->first;
		return true;
	}

	return false;
}


bool DrawToolBar::GetZoomFromXRCID(const int xrcid, int& zoom) {
	auto foundZoom = xrcidToZoom.find(xrcid);
	if (foundZoom != xrcidToZoom.end()) {
		zoom = foundZoom->second;
		return true;
	}

	return false;
}

BEGIN_EVENT_TABLE(DrawToolBar, wxToolBar)
	EVT_MENU(drawTB_NEWDRAWVERSION, DrawToolBar::NewVersionToolClicked)
END_EVENT_TABLE()
